package cn.tedu.mall.seckill.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.pojo.domain.CsmallAuthenticationInfo;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.order.service.IOmsOrderService;
import cn.tedu.mall.pojo.order.dto.OrderAddDTO;
import cn.tedu.mall.pojo.order.dto.OrderItemAddDTO;
import cn.tedu.mall.pojo.order.vo.OrderAddVO;
import cn.tedu.mall.pojo.seckill.dto.SeckillOrderAddDTO;
import cn.tedu.mall.pojo.seckill.model.SeckillSuccess;
import cn.tedu.mall.pojo.seckill.vo.SeckillCommitVO;
import cn.tedu.mall.seckill.config.RabbitMqComponentConfiguration;
import cn.tedu.mall.seckill.service.ISeckillService;
import cn.tedu.mall.seckill.utils.SeckillCacheUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

@Service
public class SeckillServiceImpl implements ISeckillService {
    /**
     * 秒杀订单中:
     *  1.需要判断当前用户是否为重复购买
     *  2.从redis中判断是否有库存
     *  3.秒杀订单转换成普通订单，需要使用Dubbo调用order模块
     *  4.秒杀成功的消息不需要立即处理，而是使用消息队列将秒杀成功的信息保存到success表
     */

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private IOmsOrderService dubboOrderService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public SeckillCommitVO commitSeckill(SeckillOrderAddDTO seckillOrderAddDTO) {
        //第一部分：利用redis去检查是否重复购买和库存是否充足
        //利用userId和skuId组合判断，如果userId+skuId的key存在，并且value大于1
        Long skuId = seckillOrderAddDTO.getSeckillOrderItemAddDTO().getSkuId();
        Long userId = getUserId();
        String reseckillCheckKey = SeckillCacheUtils.getReseckillCheckKey(skuId, userId);
        //当前使用increment（），作用是默认当前的key所对应的value+1，如果key不存在，则创建key，并且赋值1
        Long increment = stringRedisTemplate.boundValueOps(reseckillCheckKey).increment();
        if (increment>1){
            throw new CoolSharkServiceException(ResponseCode.FORBIDDEN,"您已经购买过该商品了");
        }

        //判断库存是否充足 decrement(),作用是减少1
        String stockKey = SeckillCacheUtils.getStockKey(skuId);
        Long decrement = stringRedisTemplate.boundValueOps(stockKey).decrement();
        if (decrement<0){
            //删除购买记录
            stringRedisTemplate.boundValueOps(reseckillCheckKey).decrement();
            throw new CoolSharkServiceException(ResponseCode.FORBIDDEN,"对不起，该商品已售整");
        }

        //第二部分：将秒杀订单转换成普通订单
        //SeckillOrderAddDTO        OrderAddDTO
        OrderAddDTO orderAddDTO = new OrderAddDTO();
        BeanUtils.copyProperties(seckillOrderAddDTO,orderAddDTO);
        //将SeckillOrderItemAddDTO 转换成OrderItemAddDTO
        ArrayList<OrderItemAddDTO> orderItemAddDTOS = new ArrayList<>();
        OrderItemAddDTO orderItemAddDTO = new OrderItemAddDTO();
        BeanUtils.copyProperties(seckillOrderAddDTO.getSeckillOrderItemAddDTO(),orderItemAddDTO);
        orderItemAddDTOS.add(orderItemAddDTO);
        orderAddDTO.setOrderItems(orderItemAddDTOS);
        //用户id
        orderAddDTO.setUserId(userId);
        OrderAddVO orderAddVO=null;
        try {
            orderAddVO = dubboOrderService.addOrder(orderAddDTO);
        } catch (Exception e) {
            e.printStackTrace();
            //删除购买记录，库存回填
            stringRedisTemplate.boundValueOps(reseckillCheckKey).decrement();
            stringRedisTemplate.boundValueOps(stockKey).increment();
        }

        //使用消息队列，保存秒杀成功信息
        SeckillSuccess seckillSuccess = new SeckillSuccess();
        seckillSuccess.setSeckillId(orderAddVO.getId());
        seckillSuccess.setUserId(userId);
        seckillSuccess.setUserPhone(seckillOrderAddDTO.getMobilePhone());
        seckillSuccess.setSkuId(skuId);
        seckillSuccess.setTitle(seckillOrderAddDTO.getSeckillOrderItemAddDTO().getTitle());
        seckillSuccess.setSeckillPrice(seckillOrderAddDTO.getSeckillOrderItemAddDTO().getPrice());
        seckillSuccess.setQuantity(seckillOrderAddDTO.getSeckillOrderItemAddDTO().getQuantity());
        seckillSuccess.setGmtCreate(orderAddVO.getCreateTime());
        seckillSuccess.setOrderSn(orderAddVO.getSn());

        //发宋到rabbitmq中
        rabbitTemplate.convertAndSend(
                RabbitMqComponentConfiguration.SECKILL_EX,
                RabbitMqComponentConfiguration.SECKILL_RK,
                seckillSuccess
        );
        //返回vo对象
        SeckillCommitVO seckillCommitVO = new SeckillCommitVO();
        BeanUtils.copyProperties(orderAddVO,seckillCommitVO);
        return seckillCommitVO;
    }

    public CsmallAuthenticationInfo getUserInfo(){
        UsernamePasswordAuthenticationToken authenticationToken =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();

        if (authenticationToken == null) {
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"您当前没有登陆");
        }

        CsmallAuthenticationInfo userInfo = (CsmallAuthenticationInfo) authenticationToken.getCredentials();
        return userInfo;
    }

    public Long getUserId(){
        return getUserInfo().getId();
    }
}
